﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microhard.WeixinMP.Impls;
using Microhard.WeixinMP.Interfaces;
using Microhard.WeixinMP.Models;
using Microhard.Core;
using System.Configuration;
using Microhard.Core.Net;
using System.ServiceModel.Dispatcher;


namespace Microhard.WeixinMP.Unities
{
    public class WeixinTools
    {

        public static WeixinMenuModel GetMenu(Guid cmpID, out string jsonString)
        {
            jsonString = string.Empty;
            IWXMPAuthInterface iai = new WXMPAuthInterfaceImpl();
            AccessTokenJSONModel token;
            WeixinErrorJSONModel error;
            IWXMPAccount iwa = new WXMPAccountImpl();
            var mp = iwa.GetModelByCompanyID(cmpID);
            if (GetAccessToken(mp.AppID, mp.AppSecret, out token, out error))
            {
                return iai.GetMenu(token.access_token, out jsonString);
            }
            return new WeixinMenuModel();
        }

        public static WeixinErrorJSONModel CreateMenu(Guid cmpID, string menuJson)
        {
            WeixinErrorJSONModel result = new WeixinErrorJSONModel();
            if (string.IsNullOrEmpty(menuJson))
            {
                result.errmsg = "menuJson为空";
                return result;
            }
            IWXMPAuthInterface iai = new WXMPAuthInterfaceImpl();
            AccessTokenJSONModel token;

            IWXMPAccount iwa = new WXMPAccountImpl();
            var mp = iwa.GetModelByCompanyID(cmpID);

            if (GetAccessToken(mp.AppID, mp.AppSecret, out token, out result))
            {
                return iai.CreateMenu(token.access_token, menuJson);
            }
            return result;
        }

        public static WeixinErrorJSONModel DeleteMenu(Guid cmpID)
        {
            IWXMPAuthInterface iai = new WXMPAuthInterfaceImpl();
            AccessTokenJSONModel token;
            WeixinErrorJSONModel error;

            IWXMPAccount iwa = new WXMPAccountImpl();
            var mp = iwa.GetModelByCompanyID(cmpID);

            if (GetAccessToken(mp.AppID, mp.AppSecret, out token, out error))
            {
                return iai.DeleteMenu(token.access_token);
            }
            return error;
        }

        public static WeixinUserInfo OnAuthGetUserInfo(Guid cmpID, string code, string state, out Guid companyID, out string companyName)
        {
            IWXMPAuthInterface iai = new WXMPAuthInterfaceImpl();
            var model = iai.GetCodeToToken(cmpID, code, state, out companyID, out companyName);
            if (model != null)
            {
                return iai.GetUserInfo(model.openid, model.access_token, true);
            }
            return null;
        }

        public static WeixinUserInfo GetUserInfo(Guid cmpID, string openID)
        {
            IWXMPAuthInterface iai = new WXMPAuthInterfaceImpl();
            AccessTokenJSONModel token;
            WeixinErrorJSONModel error;

            IWXMPAccount iwa = new WXMPAccountImpl();
            var mp = iwa.GetModelByCompanyID(cmpID);

            if (GetAccessToken(mp.AppID, mp.AppSecret, out token, out error))
            {
                return iai.GetUserInfo(openID, token.access_token, false);
            }
            return null;
        }

        public static byte[] DownloadMedia(Guid cmpID, string mediaID, out string fileType)
        {
            fileType = string.Empty;
            IWXMPAuthInterface iai = new WXMPAuthInterfaceImpl();
            AccessTokenJSONModel token;
            WeixinErrorJSONModel error;

            IWXMPAccount iwa = new WXMPAccountImpl();
            var mp = iwa.GetModelByCompanyID(cmpID);

            if (GetAccessToken(mp.AppID, mp.AppSecret, out token, out error))
            {
                return iai.DownloadMedia(token.access_token, mediaID, out fileType);
            }
            return null;
        }

        public static void SendTextMessage(Guid cmpID, string openID, string message)
        {
            IWXMPAuthInterface iai = new WXMPAuthInterfaceImpl();
            AccessTokenJSONModel token;
            WeixinErrorJSONModel error;

            IWXMPAccount iwa = new WXMPAccountImpl();
            var mp = iwa.GetModelByCompanyID(cmpID);

            if (GetAccessToken(mp.AppID, mp.AppSecret, out token, out error))
            {
                iai.SendTXTCustomerMessage(openID, token.access_token, message);
            }
        }

        public static void SendImageMessage(Guid cmpID, string openID, string mediaID)
        {
            IWXMPAuthInterface iai = new WXMPAuthInterfaceImpl();
            AccessTokenJSONModel token;
            WeixinErrorJSONModel error;

            IWXMPAccount iwa = new WXMPAccountImpl();
            var mp = iwa.GetModelByCompanyID(cmpID);

            if (GetAccessToken(mp.AppID, mp.AppSecret, out token, out error))
            {
                iai.SendImageCustomerMessage(openID, token.access_token, mediaID);
            }
        }

        public static void SendVideoMessage(Guid cmpID, string openID, string mediaID, string title, string description)
        {
            IWXMPAuthInterface iai = new WXMPAuthInterfaceImpl();
            AccessTokenJSONModel token;
            WeixinErrorJSONModel error;

            IWXMPAccount iwa = new WXMPAccountImpl();
            var mp = iwa.GetModelByCompanyID(cmpID);

            if (GetAccessToken(mp.AppID, mp.AppSecret, out token, out error))
            {
                iai.SendVideoCustomerMessage(openID, token.access_token, mediaID, title, description);
            }
        }

        public static void SendTextMessage(string mpUsername, string mpPassword, string txt, string toUserFakeId)
        {
            HandshakeImpl hi = new HandshakeImpl();
            IWeixinMPHtmlParser<WeixinFakeLogin_Result> im1 = new Web_LoginParserImpl();
            IWeixinMPHtmlParser<List<WeixinUserBasicModel>> im2 = new Web_ParseUsers();
            IWeixinMPHtmlParser<WeixinUserModel> im3 = new Web_ParseUserDetail();
            IWeixinMPHtmlParser<WeixinFakeSendResult> im4 = new Web_SendedResultParse();
            try
            {
                hi.SendMessage(mpUsername, mpPassword, toUserFakeId, txt, im4, im1, true);

            }
            catch (Exception ex)
            {
                Log.Error("WeixinTools.SendTextMessage", ex);
            }
        }

        public static List<string> UploadImage(string mpUsername, string mpPassword, Dictionary<string, byte[]> files)
        {
            List<string> fileIDs = new List<string>();
            HandshakeImpl hi = new HandshakeImpl();
            IWeixinMPHtmlParser<WeixinFakeLogin_Result> im1 = new Web_LoginParserImpl();
            var back = hi.Login(mpUsername, mpPassword, im1, false);
            foreach (var k in files)
            {
                string fileID = hi.UploadImage(mpUsername, mpPassword, k.Key, k.Value, new Web_UploadResultParser());
                if (!string.IsNullOrEmpty(fileID))
                {
                    fileIDs.Add(fileID);
                }
            }
            return fileIDs;
        }

        public static TicketJsonModel GetTikect(Guid cmpID, short sceneID)
        {
            TicketJsonModel rtn = new TicketJsonModel();
            AccessTokenJSONModel token;
            WeixinErrorJSONModel error;

            IWXMPAccount iwa = new WXMPAccountImpl();
            var mp = iwa.GetModelByCompanyID(cmpID);

            if (GetAccessToken(mp.AppID, mp.AppSecret, out token, out error))
            {
                string tikectUrl = ConfigurationManager.AppSettings["TicketUrl"];
                tikectUrl += token.access_token;
                string parms = "{\"action_name\": \"QR_LIMIT_SCENE\", \"action_info\": {\"scene\": {\"scene_id\": " + sceneID + "}}}";
                string strTicket = HttpReader.HttpPost(tikectUrl, parms);
                if (!string.IsNullOrEmpty(strTicket))
                {
                    JsonQueryStringConverter jqsv = new JsonQueryStringConverter();
                    rtn = (TicketJsonModel)jqsv.ConvertStringToValue(strTicket, typeof(TicketJsonModel));
                }
            }
            else
            {
                Log.Error("GetTikect", "无法获得AccessToken，Code:" + error.errcode + " Msg:" + error.errmsg);
            }
            return rtn;
        }

        public static bool GetAccessToken(string appID, string appsecret, out AccessTokenJSONModel token, out WeixinErrorJSONModel error)
        {
            bool rtn = false;
            error = new WeixinErrorJSONModel();
            token = new AccessTokenJSONModel();
            string innerGetTokenUrl = ConfigurationManager.AppSettings["GetTokenFormUrl"];
            AccessTokenCacheOperator tokenOperator = new AccessTokenCacheOperator();

            if (!string.IsNullOrEmpty(innerGetTokenUrl))
            {
                //使用内部url获得accessToken
            }
            else
            {
                //缓存中是否有accessToken
                token = tokenOperator.GetFromCache(appID);
                if (token != null && string.IsNullOrEmpty(token.access_token) == false)
                {
                    Log.Info("GetAccessToken", "从内存取出AccessToken,内容" + token.access_token);
                    return true;
                }
                else
                {
                    //向微信获取accessToken
                    string format = "&appid={0}&secret={1}";
                    string tokenUrl = ConfigurationManager.AppSettings["accessTokenUrl"];
                    tokenUrl = tokenUrl + string.Format(format, appID, appsecret);
                    JsonQueryStringConverter jqsv = new JsonQueryStringConverter();
                    string strtokenJson = string.Empty;
                    try
                    {
                        strtokenJson = HttpReader.HttpGet(tokenUrl);
                        if (!string.IsNullOrEmpty(strtokenJson))
                        {
                            token = (AccessTokenJSONModel)jqsv.ConvertStringToValue(strtokenJson, typeof(AccessTokenJSONModel));
                            rtn = true;
                            Log.Info("GetAccessToken", "从WXMP取出AccessToken,内容" + token.access_token);
                        }

                    }
                    catch (Exception ex)
                    {
                        Log.Error("GetAccessToken", ex);
                        //error = (WeixinErrorJSONModel)jqsv.ConvertStringToValue(strtokenJson, typeof(WeixinErrorJSONModel));
                    }
                    finally
                    {
                        if (rtn)
                        {
                            tokenOperator.UpdateCache(appID, token);
                        }
                    }
                }

            }
            return rtn;
        }
    }
}
